/*
 * MainWindow.java
 *
 * Created on 2 maj 2007, 11:31
 */

package edu.uj.petri.gui;

import edu.uj.petri.algorithms.Invariants;
import edu.uj.petri.algorithms.PNCoverabilityTree;
import edu.uj.petri.common.Settings;
import edu.uj.petri.controller.*;
import edu.uj.petri.document.DocumentSerializer;
import edu.uj.petri.model.Transition;
import edu.uj.petri.commands.CommandException;
import edu.uj.petri.commands.CommandStack;
import edu.uj.petri.document.Document;
import edu.uj.petri.document.DocumentModes;
import edu.uj.petri.simulation.Simulation;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JComponent;
import javax.swing.filechooser.FileFilter;
import javax.swing.plaf.basic.BasicSeparatorUI;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import javax.swing.UIManager;
import java.util.ArrayList;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.ResourceBundle;
import javax.imageio.ImageIO;
import javax.swing.JTextArea;

/**
 *
 * @author  MonikaG
 */
public class MainWindow extends JFrame implements MainWindowInterface,
        Comparable {
    
    private static final long serialVersionUID = -7883333782684433103L;
    
    /** list of all currently open documents (active and inactive) */
    private ArrayList<Document> documents;
    /** number of documents created in current session */
    private int paneNr;
    /** CommandStack for currently opened and active document */
    private transient CommandStack activeCommandStack;
    private JTextArea    firedTransitionsList;
    private List<Transition> allFired;
    private transient EventHandler eventHandler = new SelectEventHandler();
    
    private ImageIcon simulationStopIcon, simulationStartIcon;
    
    /** Creates new form MainWindow */
    public MainWindow() {
        BasicSeparatorUI basicSeparatorUI = null;
        
        this.paneNr = 1;
        
        initComponents();
        
        simulationStopIcon = new ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/stop.png"));
        simulationStartIcon = new ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/start.png"));
        setIconImage(new ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/appicon.png")).getImage());
        
        Settings settings = Settings.getInstance();
        antialiasingMenuItem.setSelected(settings.getUseAntialiasing());
        
        // set window size
        setSize(new java.awt.Dimension(630, 400));
        
        // set separators' positions - center it
        basicSeparatorUI = new BasicSeparatorUI() {
            public void paint( Graphics g, JComponent c ) {
                Dimension s = c.getSize();
                int pos = s.width/2;
                g.setColor( c.getForeground() );
                g.drawLine( pos, 0, pos++, s.height );
                g.setColor( c.getBackground() );
                g.drawLine( pos, 0, pos, s.height );
            }
        };
        this.jSeparator1.setUI(basicSeparatorUI);
        this.jSeparator2.setUI(basicSeparatorUI);
        this.jSeparator3.setUI(basicSeparatorUI);
        
        this.documents = new ArrayList<Document>();
        this.activeCommandStack = null;
        
        firedTransitionsList = new JTextArea();
        firedTransitionsList.setEditable(false);
        firedTransitionsList.setBackground(Color.lightGray);
        firedTransitionsList.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        this.mainPanel.add(firedTransitionsList, java.awt.BorderLayout.EAST);
        firedTransitionsList.setVisible(false);
        
        createNewDocument();
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        undoPopupMenu = new javax.swing.JPopupMenu();
        redoPopupMenu = new javax.swing.JPopupMenu();
        jToolBar1 = new javax.swing.JToolBar();
        newButton = new javax.swing.JButton();
        openButton = new javax.swing.JButton();
        saveButton = new javax.swing.JButton();
        closeButton = new javax.swing.JButton();
        jSeparator1 = new javax.swing.JSeparator();
        addPlaceButton = new javax.swing.JToggleButton();
        addTransitionButton = new javax.swing.JToggleButton();
        addEdgeButton = new javax.swing.JToggleButton();
        addInhibitorButton = new javax.swing.JToggleButton();
        addTokenButton = new javax.swing.JToggleButton();
        removeTokenButton = new javax.swing.JToggleButton();
        arrowButton = new javax.swing.JToggleButton();
        jSeparator2 = new javax.swing.JSeparator();
        simulateButton = new javax.swing.JToggleButton();
        randomSimulationButton = new javax.swing.JButton();
        stepSimulationButton = new javax.swing.JButton();
        batchSimulation = new javax.swing.JButton();
        jSeparator3 = new javax.swing.JSeparator();
        undoButton = new javax.swing.JButton();
        dropUndoButton = new javax.swing.JButton();
        redoButton = new javax.swing.JButton();
        dropRedoButton = new javax.swing.JButton();
        mainPanel = new javax.swing.JPanel();
        jTabbedPane1 = new javax.swing.JTabbedPane();
        jMenuBar1 = new javax.swing.JMenuBar();
        FileMenu = new javax.swing.JMenu();
        newMenuItem = new javax.swing.JMenuItem();
        openMenuItem = new javax.swing.JMenuItem();
        saveMenuItem = new javax.swing.JMenuItem();
        closeMenuItem = new javax.swing.JMenuItem();
        exportMenuItem = new javax.swing.JMenu();
        PNGMenuItem = new javax.swing.JMenuItem();
        jSeparator4 = new javax.swing.JSeparator();
        exitMenuItem = new javax.swing.JMenuItem();
        AnalysisMenu = new javax.swing.JMenu();
        coverabilityTreeMenuItem = new javax.swing.JMenuItem();
        invariantAnalysisMenuItem = new javax.swing.JMenuItem();
        viewMenu = new javax.swing.JMenu();
        antialiasingMenuItem = new javax.swing.JCheckBoxMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Enhanced Petri Net Simulator");
        addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                formKeyTyped(evt);
            }
        });
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        getAccessibleContext().setAccessibleName("mainFrame");
        newButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/new.png")));
        newButton.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("create_new_file")); // NOI18N
        newButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newButtonActionPerformed(evt);
            }
        });

        jToolBar1.add(newButton);

        openButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/open.png")));
        openButton.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("open_file")); // NOI18N
        openButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openButtonActionPerformed(evt);
            }
        });

        jToolBar1.add(openButton);

        saveButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/save.png")));
        saveButton.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("save_file_")); // NOI18N
        saveButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveButtonActionPerformed(evt);
            }
        });

        jToolBar1.add(saveButton);

        closeButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/close.png")));
        closeButton.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("close_file")); // NOI18N
        closeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeButtonActionPerformed(evt);
            }
        });

        jToolBar1.add(closeButton);

        jSeparator1.setOrientation(javax.swing.SwingConstants.VERTICAL);
        jSeparator1.setMaximumSize(new java.awt.Dimension(7, 32767));
        jSeparator1.setMinimumSize(new java.awt.Dimension(7, 0));
        jSeparator1.setPreferredSize(new java.awt.Dimension(7, 0));
        jToolBar1.add(jSeparator1);

        addPlaceButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/place.png")));
        addPlaceButton.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("create_new_place")); // NOI18N
        addPlaceButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addPlaceButtonActionPerformed(evt);
            }
        });
        addPlaceButton.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                addPlaceButtonKeyPressed(evt);
            }
            public void keyTyped(java.awt.event.KeyEvent evt) {
                addPlaceButtonKeyTyped(evt);
            }
        });

        jToolBar1.add(addPlaceButton);

        addTransitionButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/transition.png")));
        addTransitionButton.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("create_new_transition")); // NOI18N
        addTransitionButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addTransitionButtonActionPerformed(evt);
            }
        });
        addTransitionButton.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                addTransitionButtonKeyPressed(evt);
            }
            public void keyTyped(java.awt.event.KeyEvent evt) {
                addTransitionButtonKeyTyped(evt);
            }
        });

        jToolBar1.add(addTransitionButton);

        addEdgeButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/edge.png")));
        addEdgeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addEdgeButtonActionPerformed(evt);
            }
        });
        addEdgeButton.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                addEdgeButtonKeyPressed(evt);
            }
            public void keyTyped(java.awt.event.KeyEvent evt) {
                addEdgeButtonKeyTyped(evt);
            }
        });

        jToolBar1.add(addEdgeButton);

        addInhibitorButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/inhibitor.png")));
        addInhibitorButton.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("create_new_inhibitor")); // NOI18N
        addInhibitorButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addInhibitorButtonActionPerformed(evt);
            }
        });
        addInhibitorButton.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                addInhibitorButtonKeyPressed(evt);
            }
            public void keyTyped(java.awt.event.KeyEvent evt) {
                addInhibitorButtonKeyTyped(evt);
            }
        });

        jToolBar1.add(addInhibitorButton);

        addTokenButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/add.png")));
        addTokenButton.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("add_token")); // NOI18N
        addTokenButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addTokenButtonActionPerformed(evt);
            }
        });
        addTokenButton.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                addTokenButtonKeyPressed(evt);
            }
            public void keyTyped(java.awt.event.KeyEvent evt) {
                addTokenButtonKeyTyped(evt);
            }
        });

        jToolBar1.add(addTokenButton);

        removeTokenButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/remove.png")));
        removeTokenButton.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("remove_token")); // NOI18N
        removeTokenButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeTokenButtonActionPerformed(evt);
            }
        });
        removeTokenButton.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                removeTokenButtonKeyPressed(evt);
            }
            public void keyTyped(java.awt.event.KeyEvent evt) {
                removeTokenButtonKeyTyped(evt);
            }
        });

        jToolBar1.add(removeTokenButton);

        arrowButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/arrow.png")));
        arrowButton.setSelected(true);
        arrowButton.setToolTipText("");
        arrowButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                arrowButtonActionPerformed(evt);
            }
        });
        arrowButton.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                arrowButtonKeyPressed(evt);
            }
            public void keyTyped(java.awt.event.KeyEvent evt) {
                arrowButtonKeyTyped(evt);
            }
        });

        jToolBar1.add(arrowButton);

        jSeparator2.setOrientation(javax.swing.SwingConstants.VERTICAL);
        jSeparator2.setMaximumSize(new java.awt.Dimension(7, 32767));
        jSeparator2.setMinimumSize(new java.awt.Dimension(7, 0));
        jSeparator2.setPreferredSize(new java.awt.Dimension(7, 0));
        jToolBar1.add(jSeparator2);

        simulateButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/start.png")));
        simulateButton.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("turn_on_simulation_mode")); // NOI18N
        simulateButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                simulateButtonActionPerformed(evt);
            }
        });

        jToolBar1.add(simulateButton);

        randomSimulationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/start_1.png")));
        randomSimulationButton.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("next_transition")); // NOI18N
        randomSimulationButton.setEnabled(false);
        randomSimulationButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                randomSimulationButtonActionPerformed(evt);
            }
        });

        jToolBar1.add(randomSimulationButton);

        stepSimulationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/start_R.png")));
        stepSimulationButton.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("fire_number_of_random_transitions")); // NOI18N
        stepSimulationButton.setEnabled(false);
        stepSimulationButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stepSimulationButtonActionPerformed(evt);
            }
        });

        jToolBar1.add(stepSimulationButton);

        batchSimulation.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/start_batch.png")));
        batchSimulation.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("fire_a_batch_of_transitions")); // NOI18N
        batchSimulation.setEnabled(false);
        batchSimulation.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                batchSimulationActionPerformed(evt);
            }
        });

        jToolBar1.add(batchSimulation);

        jSeparator3.setOrientation(javax.swing.SwingConstants.VERTICAL);
        jSeparator3.setMaximumSize(new java.awt.Dimension(7, 32767));
        jSeparator3.setMinimumSize(new java.awt.Dimension(7, 0));
        jSeparator3.setPreferredSize(new java.awt.Dimension(7, 0));
        jToolBar1.add(jSeparator3);

        undoButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/undo.png")));
        undoButton.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("Undo")); // NOI18N
        undoButton.setEnabled(false);
        undoButton.setInheritsPopupMenu(true);
        undoButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                undoButtonMouseClicked(evt);
            }
        });

        jToolBar1.add(undoButton);

        dropUndoButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/small_arrow.png")));
        dropUndoButton.setEnabled(false);
        dropUndoButton.setMaximumSize(new java.awt.Dimension(10, 29));
        dropUndoButton.setMinimumSize(new java.awt.Dimension(10, 29));
        dropUndoButton.setPreferredSize(new java.awt.Dimension(10, 29));
        dropUndoButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                dropUndoButtonMouseClicked(evt);
            }
        });

        jToolBar1.add(dropUndoButton);

        redoButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/redo.png")));
        redoButton.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("Redo")); // NOI18N
        redoButton.setEnabled(false);
        redoButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                redoButtonMouseClicked(evt);
            }
        });

        jToolBar1.add(redoButton);

        dropRedoButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/uj/petri/gui/icons/small_arrow.png")));
        dropRedoButton.setEnabled(false);
        dropRedoButton.setMaximumSize(new java.awt.Dimension(10, 29));
        dropRedoButton.setMinimumSize(new java.awt.Dimension(10, 29));
        dropRedoButton.setPreferredSize(new java.awt.Dimension(15, 29));
        dropRedoButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                dropRedoButtonMouseClicked(evt);
            }
        });

        jToolBar1.add(dropRedoButton);

        getContentPane().add(jToolBar1, java.awt.BorderLayout.NORTH);

        mainPanel.setLayout(new java.awt.BorderLayout());

        jTabbedPane1.setDoubleBuffered(true);
        jTabbedPane1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jTabbedPane1MouseClicked(evt);
            }
            public void mousePressed(java.awt.event.MouseEvent evt) {
                jTabbedPane1MousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                jTabbedPane1MouseReleased(evt);
            }
        });
        jTabbedPane1.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jTabbedPane1StateChanged(evt);
            }
        });
        jTabbedPane1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                jTabbedPane1MouseDragged(evt);
            }
            public void mouseMoved(java.awt.event.MouseEvent evt) {
                jTabbedPane1MouseMoved(evt);
            }
        });
        jTabbedPane1.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                jTabbedPane1KeyPressed(evt);
            }
            public void keyReleased(java.awt.event.KeyEvent evt) {
                jTabbedPane1KeyReleased(evt);
            }
            public void keyTyped(java.awt.event.KeyEvent evt) {
                jTabbedPane1KeyTyped(evt);
            }
        });

        mainPanel.add(jTabbedPane1, java.awt.BorderLayout.CENTER);

        getContentPane().add(mainPanel, java.awt.BorderLayout.CENTER);

        FileMenu.setText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("File")); // NOI18N
        newMenuItem.setText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("New")); // NOI18N
        newMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newMenuItemActionPerformed(evt);
            }
        });

        FileMenu.add(newMenuItem);

        openMenuItem.setText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("Open")); // NOI18N
        openMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openMenuItemActionPerformed(evt);
            }
        });

        FileMenu.add(openMenuItem);

        saveMenuItem.setText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("Save")); // NOI18N
        saveMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveMenuItemActionPerformed(evt);
            }
        });

        FileMenu.add(saveMenuItem);

        closeMenuItem.setText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("Close")); // NOI18N
        closeMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeMenuItemActionPerformed(evt);
            }
        });

        FileMenu.add(closeMenuItem);

        exportMenuItem.setText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("Export")); // NOI18N
        PNGMenuItem.setText("PNG");
        PNGMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                PNGMenuItemActionPerformed(evt);
            }
        });

        exportMenuItem.add(PNGMenuItem);

        FileMenu.add(exportMenuItem);

        FileMenu.add(jSeparator4);

        exitMenuItem.setText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("Exit")); // NOI18N
        exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exitMenuItemActionPerformed(evt);
            }
        });

        FileMenu.add(exitMenuItem);

        jMenuBar1.add(FileMenu);

        AnalysisMenu.setText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("Analysis")); // NOI18N
        coverabilityTreeMenuItem.setText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("Coverability_Tree")); // NOI18N
        coverabilityTreeMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                coverabilityTreeMenuItemActionPerformed(evt);
            }
        });

        AnalysisMenu.add(coverabilityTreeMenuItem);

        invariantAnalysisMenuItem.setText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("Invariant_Analysis")); // NOI18N
        invariantAnalysisMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                invariantAnalysisMenuItemActionPerformed(evt);
            }
        });

        AnalysisMenu.add(invariantAnalysisMenuItem);

        jMenuBar1.add(AnalysisMenu);

        viewMenu.setText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("View")); // NOI18N
        antialiasingMenuItem.setText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("Antialiasing")); // NOI18N
        antialiasingMenuItem.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                antialiasingMenuItemStateChanged(evt);
            }
        });

        viewMenu.add(antialiasingMenuItem);

        jMenuBar1.add(viewMenu);

        setJMenuBar(jMenuBar1);

    }// </editor-fold>//GEN-END:initComponents

    private void antialiasingMenuItemStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_antialiasingMenuItemStateChanged
        Settings settings = Settings.getInstance();
        settings.setUseAntialiasing(antialiasingMenuItem.isSelected());
    }//GEN-LAST:event_antialiasingMenuItemStateChanged

    private void arrowButtonKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_arrowButtonKeyPressed
        eventHandler.keyPressed( evt.getKeyCode() );
    }//GEN-LAST:event_arrowButtonKeyPressed

    private void removeTokenButtonKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_removeTokenButtonKeyPressed
        eventHandler.keyPressed( evt.getKeyCode() );
    }//GEN-LAST:event_removeTokenButtonKeyPressed

    private void addTokenButtonKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_addTokenButtonKeyPressed
        eventHandler.keyPressed( evt.getKeyCode() );
    }//GEN-LAST:event_addTokenButtonKeyPressed

    private void addEdgeButtonKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_addEdgeButtonKeyPressed
        eventHandler.keyPressed( evt.getKeyCode() );
    }//GEN-LAST:event_addEdgeButtonKeyPressed

    private void addTransitionButtonKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_addTransitionButtonKeyPressed
        eventHandler.keyPressed( evt.getKeyCode() );
    }//GEN-LAST:event_addTransitionButtonKeyPressed

    private void jTabbedPane1KeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jTabbedPane1KeyPressed
        eventHandler.keyPressed( evt.getKeyCode() );
    }//GEN-LAST:event_jTabbedPane1KeyPressed

    private void addPlaceButtonKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_addPlaceButtonKeyPressed
        eventHandler.keyPressed( evt.getKeyCode() );
    }//GEN-LAST:event_addPlaceButtonKeyPressed

    private void addInhibitorButtonKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_addInhibitorButtonKeyPressed

        eventHandler.keyPressed( evt.getKeyCode() );
    }//GEN-LAST:event_addInhibitorButtonKeyPressed

    private void jTabbedPane1KeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jTabbedPane1KeyReleased
// TODO add your handling code here:
    }//GEN-LAST:event_jTabbedPane1KeyReleased

    private void arrowButtonKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_arrowButtonKeyTyped

        
    }//GEN-LAST:event_arrowButtonKeyTyped

    private void removeTokenButtonKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_removeTokenButtonKeyTyped
        
    }//GEN-LAST:event_removeTokenButtonKeyTyped

    private void addTokenButtonKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_addTokenButtonKeyTyped

        
    }//GEN-LAST:event_addTokenButtonKeyTyped

    private void addInhibitorButtonKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_addInhibitorButtonKeyTyped
        
        
    }//GEN-LAST:event_addInhibitorButtonKeyTyped

    private void addEdgeButtonKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_addEdgeButtonKeyTyped
        
        
    }//GEN-LAST:event_addEdgeButtonKeyTyped

    private void addTransitionButtonKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_addTransitionButtonKeyTyped
        
        
    }//GEN-LAST:event_addTransitionButtonKeyTyped

    private void addPlaceButtonKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_addPlaceButtonKeyTyped

        
    }//GEN-LAST:event_addPlaceButtonKeyTyped
    
    private void jTabbedPane1MouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTabbedPane1MouseDragged
        
        evt.translatePoint( jTabbedPane1.getX() - jTabbedPane1.getSelectedComponent().getX(),
                jTabbedPane1.getY() - jTabbedPane1.getSelectedComponent().getY() );
        
        Point2D p = Document.getActiveDocument().getCanvas().convertScreenToCanvas( evt.getX(), evt.getY() );
        eventHandler.mouseDragged( p.getX(), p.getY());
    }//GEN-LAST:event_jTabbedPane1MouseDragged
    
    private void randomSimulationButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_randomSimulationButtonActionPerformed
        Simulation simulation = Document.getActiveDocument().getSimulation();
        simulation.fireRandomTransitions(1,0);
    }//GEN-LAST:event_randomSimulationButtonActionPerformed
    
    private void formKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_formKeyTyped
        
        eventHandler.keyPressed( evt.getKeyCode() );
    }//GEN-LAST:event_formKeyTyped
    
    private void jTabbedPane1KeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jTabbedPane1KeyTyped
        
        eventHandler.keyPressed( evt.getKeyCode() );
    }//GEN-LAST:event_jTabbedPane1KeyTyped
    
    
    private void dropRedoButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_dropRedoButtonMouseClicked
        if (this.redoButton.isEnabled()) {
            this.redoPopupMenu.show(evt.getComponent(),
                    0,  // I don't know why but it works :)
                    this.dropRedoButton.getY() + this.dropRedoButton.getHeight());
        }
    }//GEN-LAST:event_dropRedoButtonMouseClicked
    
    private void dropUndoButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_dropUndoButtonMouseClicked
        if (this.undoButton.isEnabled()) {
            this.undoPopupMenu.show(evt.getComponent(),
                    0,  // I don't know why but it works :)
                    this.dropUndoButton.getY() + this.dropUndoButton.getHeight());
        }
    }//GEN-LAST:event_dropUndoButtonMouseClicked
    
    private void jTabbedPane1MousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTabbedPane1MousePressed
        
        
        evt.translatePoint( jTabbedPane1.getX() - jTabbedPane1.getSelectedComponent().getX(),
                jTabbedPane1.getY() - jTabbedPane1.getSelectedComponent().getY() );
        
        Point2D p = Document.getActiveDocument().getCanvas().convertScreenToCanvas( evt.getX(), evt.getY() );
        
        eventHandler.mouseButtonDown( p.getX(), p.getY());
        
    }//GEN-LAST:event_jTabbedPane1MousePressed
    
    private void jTabbedPane1MouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTabbedPane1MouseReleased
        
        
        evt.translatePoint( jTabbedPane1.getX() - jTabbedPane1.getSelectedComponent().getX(),
                jTabbedPane1.getY() - jTabbedPane1.getSelectedComponent().getY() );
        
        Point2D p = Document.getActiveDocument().getCanvas().convertScreenToCanvas( evt.getX(), evt.getY() );
        
        eventHandler.mouseButtonUp( p.getX(), p.getY());
        
    }//GEN-LAST:event_jTabbedPane1MouseReleased
    
    private void jTabbedPane1MouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTabbedPane1MouseMoved
        
        evt.translatePoint( jTabbedPane1.getX() - jTabbedPane1.getSelectedComponent().getX(),
                jTabbedPane1.getY() - jTabbedPane1.getSelectedComponent().getY() );
        
        Point2D p = Document.getActiveDocument().getCanvas().convertScreenToCanvas( evt.getX(), evt.getY() );
        
        eventHandler.mouseMove( p.getX(), p.getY(), evt.getButton());
    }//GEN-LAST:event_jTabbedPane1MouseMoved
    
    public void paint( Graphics g ) {
        super.paint(g);
        //Document.getActiveDocument().getView().draw(  new SwingCanvas( jTabbedPane1.getSelectedComponent(), 1, 10) );
        //Document.getActiveDocument().getView().draw();
    }
    
    private void jTabbedPane1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTabbedPane1MouseClicked
        
        
        evt.translatePoint( jTabbedPane1.getX() - jTabbedPane1.getSelectedComponent().getX(),
                jTabbedPane1.getY() - jTabbedPane1.getSelectedComponent().getY() );
        
        Point2D p = Document.getActiveDocument().getCanvas().convertScreenToCanvas( evt.getX(), evt.getY() );
        
        if( evt.getClickCount() == 2) eventHandler.doubleClick( p.getX(), p.getY());
        else {
            if (evt.getButton() == MouseEvent.BUTTON1) eventHandler.click( p.getX(), p.getY());
            else if (evt.getButton() == MouseEvent.BUTTON3) eventHandler.rightClick( p.getX(), p.getY());
            Document.getActiveDocument().getView().draw();
        }
    }//GEN-LAST:event_jTabbedPane1MouseClicked
    
    
    private void coverabilityTreeMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_coverabilityTreeMenuItemActionPerformed
        InfoWindow infoWindow = new InfoWindow();
        PNCoverabilityTree ct = new PNCoverabilityTree(this.getActiveDocument().getModel());
        infoWindow.setTitle(ResourceBundle.getBundle("edu/uj/petri/messages").getString("Coverability_tree"));
        infoWindow.setInfo(ct.GetTree());
        infoWindow.setVisible(true);
    }//GEN-LAST:event_coverabilityTreeMenuItemActionPerformed
    
    
    private void invariantAnalysisMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_invariantAnalysisMenuItemActionPerformed
        InfoWindow infoWindow = new InfoWindow();
        Invariants invariants = new Invariants(this.getActiveDocument().getModel());
        infoWindow.setTitle(ResourceBundle.getBundle("edu/uj/petri/messages").getString("Invariants_info"));
        infoWindow.setInfo(invariants.GetResult());
        infoWindow.setVisible(true);
    }//GEN-LAST:event_invariantAnalysisMenuItemActionPerformed
    
    private void batchSimulationActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_batchSimulationActionPerformed
        List<Transition> toFire;
        int delay;
        TransitionsSelectionWindow selectionWindow = new TransitionsSelectionWindow(this, true);
        Collection<Transition> trans = this.getActiveDocument().getModel().getAllTransitions();
        
        for(Transition transition : trans)
            selectionWindow.add(transition);
        
        selectionWindow.setVisible(true);
        
        toFire = selectionWindow.getSelectedTransitions();
        delay = selectionWindow.getDelay();
        Simulation simulation = getActiveDocument().getSimulation();
        simulation.fireTransitions(toFire, delay);
        
    }//GEN-LAST:event_batchSimulationActionPerformed
    
    private void stepSimulationButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_stepSimulationButtonActionPerformed
        RandomTransitionsSettingsWindow window = new RandomTransitionsSettingsWindow(this, true);
        window.setVisible(true);
        
        Simulation simulation = getActiveDocument().getSimulation();
        simulation.fireRandomTransitions(window.getNumberOfTransitions(), window.getDelay());
        
    }//GEN-LAST:event_stepSimulationButtonActionPerformed
    
    private void saveMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveMenuItemActionPerformed
        saveButtonActionPerformed(evt);
    }//GEN-LAST:event_saveMenuItemActionPerformed
    
    private void openMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openMenuItemActionPerformed
        openButtonActionPerformed(evt);
    }//GEN-LAST:event_openMenuItemActionPerformed
    
    private void PNGMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_PNGMenuItemActionPerformed
        int width  = this.jTabbedPane1.getSelectedComponent().getWidth();
        int height = this.jTabbedPane1.getSelectedComponent().getHeight();
        
        BufferedImage image = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = image.createGraphics();
        jTabbedPane1.getSelectedComponent().paint(g2);
        g2.dispose();
        try {
            JFileChooser fileChooser = new JFileChooser();
            fileChooser.setFileFilter(new FileFilter() {
                public boolean accept(java.io.File file) {
                    String name = file.getName();
                    if (file.isDirectory()) {
                        return true;
                    } else {
                        int index = name.lastIndexOf('.');
                        if (0 <= index) {
                            if (name.substring(name.lastIndexOf('.')).toLowerCase().equals(".png")) {
                                return true;
                            }
                        }
                    }
                    return false;
                }
                
                public String getDescription() {
                    return ResourceBundle.getBundle("edu/uj/petri/messages").getString("PNG_files");
                }
            });
            
            fileChooser.showOpenDialog(this);
            
            if (fileChooser.getSelectedFile() == null)
                return;
            
            ImageIO.write(image, "png", fileChooser.getSelectedFile());
        } catch(IOException e) {
            System.out.println(e.getMessage());
        }
    }//GEN-LAST:event_PNGMenuItemActionPerformed
    
    private void arrowButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_arrowButtonActionPerformed
        setDesignButtonDeselected();
        this.arrowButton.setSelected(true);
        eventHandler = new SelectEventHandler();
    }//GEN-LAST:event_arrowButtonActionPerformed
    
    private void removeTokenButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeTokenButtonActionPerformed
        setDesignButtonDeselected();
        this.removeTokenButton.setSelected(true);
        eventHandler = new RemoveTokenEventHandler();
    }//GEN-LAST:event_removeTokenButtonActionPerformed
    
    private void addTokenButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addTokenButtonActionPerformed
        setDesignButtonDeselected();
        this.addTokenButton.setSelected(true);
        eventHandler = new AddTokensEventHandler();
    }//GEN-LAST:event_addTokenButtonActionPerformed
    
    private void addInhibitorButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addInhibitorButtonActionPerformed
        setDesignButtonDeselected();
        this.addInhibitorButton.setSelected(true);
        eventHandler = new NewInhibitorArcEventHandler();
    }//GEN-LAST:event_addInhibitorButtonActionPerformed
    
    private void addEdgeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addEdgeButtonActionPerformed
        setDesignButtonDeselected();
        this.addEdgeButton.setSelected(true);
        eventHandler = new NewNormalArcEventHandler();
    }//GEN-LAST:event_addEdgeButtonActionPerformed
    
    private void addTransitionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addTransitionButtonActionPerformed
        setDesignButtonDeselected();
        this.addTransitionButton.setSelected(true);
        eventHandler = new NewTransitionEventHandler();
    }//GEN-LAST:event_addTransitionButtonActionPerformed
    
    private void addPlaceButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addPlaceButtonActionPerformed
        setDesignButtonDeselected();
        this.addPlaceButton.setSelected(true);
        eventHandler = new NewPlaceEventHandler();
        //System.out.println(Document.getActiveDocument().getName());
    }//GEN-LAST:event_addPlaceButtonActionPerformed
    
    /**
     * Open file and deserialize information about petri net saved in it.
     */
    private void openButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openButtonActionPerformed
        JFileChooser    fileChooser = new JFileChooser();
        Document        doc         = null;
        JPanel          panel       = null;
        
        fileChooser.showOpenDialog(this);
        
        // if no file was chosen:
        if (fileChooser.getSelectedFile() == null)
            return;
        
        DocumentSerializer serializer = new DocumentSerializer();
        
        // deserialize model and view
        try {
            serializer.read(new FileInputStream(fileChooser.getSelectedFile()));
            
            panel = new JPanel();
            panel.setBackground(Color.WHITE);
            doc = new Document(new SwingCanvas(panel, 5.0, 5.0), serializer.getModel(), serializer.getView());
            
            this.documents.add(doc);
            doc.setName(fileChooser.getSelectedFile().getName());
            jTabbedPane1.addTab(doc.getName(), panel);
            doc.setMode(DocumentModes.DESIGN, this);
            
            jTabbedPane1.setSelectedIndex(jTabbedPane1.getComponentCount()-1);
            
            this.closeButton.setEnabled(true);
            this.closeMenuItem.setEnabled(true);
            
        } catch (IOException e) {
            JOptionPane.showMessageDialog(this, ResourceBundle.getBundle("edu/uj/petri/messages").getString("Unappropriate_file_format"));
            return;
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        
    }//GEN-LAST:event_openButtonActionPerformed
    
    /**
     * Save file with petri net.
     */
    private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveButtonActionPerformed
        JFileChooser    fileChooser = new JFileChooser();
        
        fileChooser.showSaveDialog(this);
        
        // if no file was chosen:
        if (fileChooser.getSelectedFile() == null)
            return;
        
        DocumentSerializer serializer = new DocumentSerializer();
        
        try {
            serializer.setOutputStream(new FileOutputStream(fileChooser.getSelectedFile()));
            
            this.getActiveDocument().save(serializer);
            
            this.getActiveDocument().setName(fileChooser.getSelectedFile().getName());
            this.jTabbedPane1.setTitleAt(this.jTabbedPane1.getSelectedIndex(), fileChooser.getSelectedFile().getName());
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        
    }//GEN-LAST:event_saveButtonActionPerformed
    
    /**
     * Turn on/off simulation mode.
     */
    private void simulateButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_simulateButtonActionPerformed
        // if there are no tabs(documents)
        if (jTabbedPane1.getComponentCount() < 1)
            return;
        
        DocumentModes mode;
        // turn on simulation mode
        if (simulateButton.isSelected()) {
            mode = DocumentModes.SIMULATION;
            simulateButton.setIcon(simulationStopIcon);
            simulateButton.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("turn_off_simulation_mode"));
            setDesignButtonDeselected();
            eventHandler = new SimulationEventHandler();
        }
        // turn off simulation mode
        else {
            mode = DocumentModes.DESIGN;
            simulateButton.setIcon(simulationStartIcon);
            simulateButton.setToolTipText(ResourceBundle.getBundle("edu/uj/petri/messages").getString("turn_on_simulation_mode"));
            arrowButtonActionPerformed(null); // sets event handler
        }
        
        Document document = getActiveDocument();
        document.setMode(mode, this);
    }//GEN-LAST:event_simulateButtonActionPerformed
    
    /**
     * Show redo command list.
     */
    private void redoButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_redoButtonMouseClicked
        if (this.redoButton.isEnabled())
            this.redoPerformed(0);
    }//GEN-LAST:event_redoButtonMouseClicked
    
    /**
     * Show undo command list.
     */
    private void undoButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_undoButtonMouseClicked
        if (this.undoButton.isEnabled())
            this.undoPerformed(0);
    }//GEN-LAST:event_undoButtonMouseClicked
    
    /**
     * This method is called when tab(document) selection changes.
     */
    private void jTabbedPane1StateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jTabbedPane1StateChanged
        // if there has been removed last tab(document)
        if (jTabbedPane1.getComponentCount() < 2)
            return;
        getActiveDocument().setActive(this);
    }//GEN-LAST:event_jTabbedPane1StateChanged
    
    /**
     * Change betwen design and simulation DocumentModes.
     */
    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        exitFromProgram();
    }//GEN-LAST:event_formWindowClosing
    
    /**
     * Exit from program.
     */
    private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed
        exitFromProgram();
    }//GEN-LAST:event_exitMenuItemActionPerformed
    
    /**
     * Close active tab(document).
     */
    private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
        closePane(this.jTabbedPane1.getSelectedIndex());
    }//GEN-LAST:event_closeButtonActionPerformed
    
    /**
     * Close active tab(document).
     */
    private void closeMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeMenuItemActionPerformed
        closePane(this.jTabbedPane1.getSelectedIndex());
    }//GEN-LAST:event_closeMenuItemActionPerformed
    
    /**
     * Create new document (for petri net).
     */
    private void newButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newButtonActionPerformed
        createNewDocument();
    }//GEN-LAST:event_newButtonActionPerformed
    
    /**
     * Create new document (for petri net).
     */
    private void newMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newMenuItemActionPerformed
        createNewDocument();
    }//GEN-LAST:event_newMenuItemActionPerformed
    
    /**
     * Main method in program:
     * - gets settings for look&feel,
     * - shows program's main window,
     *
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        Settings settings = Settings.getInstance();
        settings.load();
        try {
            UIManager.setLookAndFeel(settings.getLookAndFeelName());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MainWindow().setVisible(true);
            }
        });
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenu AnalysisMenu;
    private javax.swing.JMenu FileMenu;
    private javax.swing.JMenuItem PNGMenuItem;
    private javax.swing.JToggleButton addEdgeButton;
    private javax.swing.JToggleButton addInhibitorButton;
    private javax.swing.JToggleButton addPlaceButton;
    private javax.swing.JToggleButton addTokenButton;
    private javax.swing.JToggleButton addTransitionButton;
    private javax.swing.JCheckBoxMenuItem antialiasingMenuItem;
    private javax.swing.JToggleButton arrowButton;
    private javax.swing.JButton batchSimulation;
    private javax.swing.JButton closeButton;
    private javax.swing.JMenuItem closeMenuItem;
    private javax.swing.JMenuItem coverabilityTreeMenuItem;
    private javax.swing.JButton dropRedoButton;
    private javax.swing.JButton dropUndoButton;
    private javax.swing.JMenuItem exitMenuItem;
    private javax.swing.JMenu exportMenuItem;
    private javax.swing.JMenuItem invariantAnalysisMenuItem;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JSeparator jSeparator2;
    private javax.swing.JSeparator jSeparator3;
    private javax.swing.JSeparator jSeparator4;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JButton newButton;
    private javax.swing.JMenuItem newMenuItem;
    private javax.swing.JButton openButton;
    private javax.swing.JMenuItem openMenuItem;
    private javax.swing.JButton randomSimulationButton;
    private javax.swing.JButton redoButton;
    private javax.swing.JPopupMenu redoPopupMenu;
    private javax.swing.JToggleButton removeTokenButton;
    private javax.swing.JButton saveButton;
    private javax.swing.JMenuItem saveMenuItem;
    private javax.swing.JToggleButton simulateButton;
    private javax.swing.JButton stepSimulationButton;
    private javax.swing.JButton undoButton;
    private javax.swing.JPopupMenu undoPopupMenu;
    private javax.swing.JMenu viewMenu;
    // End of variables declaration//GEN-END:variables
    
    
    /**
     * Create new document (for petri net) and set it's tab as active.
     */
    
    
    public static class MyJPanel extends JPanel  {
        
        public MyJPanel() {
            super(true); // double buffered
            //doubl
        }
        
        public void paint( Graphics g ){
            
            super.paint(g);
            Document.getActiveDocument().getView().draw();
        }
        
        /*public void paintComponent( Graphics g ){
         
            super.paint(g);
            Document.getActiveDocument().getView().draw();
        }*/
        
        private static final long serialVersionUID = -7821388875966043L;
    }
    
    private void createNewDocument() {
        
        JPanel panel = new MyJPanel();
        panel.setBackground(Color.WHITE);
        SwingCanvas canvas = new SwingCanvas(panel, 1, 1);
        Document doc = new Document(canvas);
        
        this.documents.add(doc);
        doc.setName(ResourceBundle.getBundle("edu/uj/petri/messages").getString("new_") + this.paneNr);
        ++this.paneNr;
        jTabbedPane1.addTab(doc.getName(), panel);
        doc.setMode(DocumentModes.DESIGN, this);
        
        jTabbedPane1.setSelectedIndex(jTabbedPane1.getComponentCount()-1);
        doc.setActive(this);
        
        doc.setCanvas(canvas);
        
        this.closeButton.setEnabled(true);
        this.closeMenuItem.setEnabled(true);
    }
    
    /**
     * Returns active document (this one from active tab).
     *
     * @return active document (this one from active tab)
     */
    private Document getActiveDocument() {
        return documents.get(jTabbedPane1.getSelectedIndex());
    }
    
    /**
     * Set undo command list - get only 10 first commands to undo.
     */
    private void setUndoCommandList(String[] undoList) {
        this.undoPopupMenu.removeAll();
        for (int i = 0;  (i < undoList.length) && (i < 10); i++) {
            JMenuItem menuItem = new JMenuItem(undoList[i]);
            
            menuItem.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent evt) {
                    undoPerformed(undoPopupMenu.getComponentIndex(((JMenuItem)evt.getSource()))); // method from class MainWindow
                }
            });
            
            this.undoPopupMenu.add(menuItem);
        }
    }
    
    /**
     * Set redo command list - get only 10 first commands to redo.
     */
    private void setRedoCommandList(String[] redoList) {
        this.redoPopupMenu.removeAll();
        for (int i = 0;  (i < redoList.length) && (i < 10); i++) {
            JMenuItem menuItem = new JMenuItem(redoList[i]);
            
            menuItem.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent evt) {
                    redoPerformed(redoPopupMenu.getComponentIndex(((JMenuItem)evt.getSource()))); // method from class MainWindow
                }
            });
            
            this.redoPopupMenu.add(menuItem);
        }
    }
    
    /**
     * Close document from given index.
     *
     * @param index index of document to close
     */
    private void closePane(int index) {
        int result = -1;
         
        /*if (documents.get(index).getChanged()) {
            result = JOptionPane.showConfirmDialog(this, "Do you really want to close file '" + jTabbedPane1.getTitleAt(jTabbedPane1.getSelectedIndex()) + "'?",
                    "Close file", JOptionPane.YES_NO_OPTION);
         
            if (result == JOptionPane.YES_OPTION) {
                this.documents.remove(index);
                this.jTabbedPane1.remove(index);
         
                if (jTabbedPane1.getComponentCount() == 0) {
                    this.closeButton.setEnabled(false);
                    this.closeMenuItem.setEnabled(false);
                }
            }
        }
        // close without saving
        else {*/
            this.documents.remove(index);
            this.jTabbedPane1.remove(index);
        //}
    }
    
    /**
     * Exit from program:
     * - save actual settings,
     * - check if all open documents was saved,
     */
    private void exitFromProgram() {
        // save settings
        Settings.getInstance().save();
        // close all open documents
        for (int i = this.documents.size(); i > 0 ; i--) {
            this.closePane(0);
        }
        System.exit(0);
    }
    
    /**
     * Select all design buttons deselected.
     */
    public void setDesignButtonDeselected() {
        this.addPlaceButton.setSelected(false);
        this.addTransitionButton.setSelected(false);
        this.addEdgeButton.setSelected(false);
        this.addInhibitorButton.setSelected(false);
        this.addTokenButton.setSelected(false);
        this.removeTokenButton.setSelected(false);
        this.arrowButton.setSelected(false);
    }
    
    /**
     * Set all design button enabled/disabled.
     *
     * @param enabled tells if all design buttons should be enabled or disabled
     */
    public void setDesignButtonsEnabled(boolean enabled) {
        this.addPlaceButton.setEnabled(enabled);
        this.addTransitionButton.setEnabled(enabled);
        this.addEdgeButton.setEnabled(enabled);
        this.addInhibitorButton.setEnabled(enabled);
        this.addTokenButton.setEnabled(enabled);
        this.removeTokenButton.setEnabled(enabled);
        this.arrowButton.setEnabled(enabled);
        this.firedTransitionsList.setVisible(!enabled);
    }
    
    /**
     * Set all simulation button enabled/disabled.
     *
     * @param enabled tells if all simulation buttons should be enabled or disabled
     */
    public void setSimulationButtonsEnabled(boolean enabled) {
        this.randomSimulationButton.setEnabled(enabled);
        this.stepSimulationButton.setEnabled(enabled);
        this.batchSimulation.setEnabled(enabled);
    }
    
    /**
     * Sets current command stack.
     * Class should subscribe its observers to the stack (and unsubscribe from previous stack).
     */
    public void setCommandStack(CommandStack commandStack) {
        // unsubscribe from previous commandStack
        if (this.activeCommandStack != null)
            this.activeCommandStack.unsubscribe(this);
        // remember command stack somewhere in a private variable
        this.activeCommandStack = commandStack;
        // subscribe to new commandStack
        this.activeCommandStack.subscribe(this);
        // check if redo and undo are possible, enable or disable buttons
        this.undoButton.setEnabled(this.activeCommandStack.undoPossible());
        this.dropUndoButton.setEnabled(this.activeCommandStack.undoPossible());
        this.redoButton.setEnabled(this.activeCommandStack.redoPossible());
        this.dropRedoButton.setEnabled(this.activeCommandStack.redoPossible());
        // read list of command names in undo/redo lists
        if (this.activeCommandStack.undoPossible())
            this.setUndoCommandList(this.activeCommandStack.getAvailForUndo());
        if (this.activeCommandStack.redoPossible())
            this.setRedoCommandList(this.activeCommandStack.getAvailForRedo());
    }
    
    /**
     * Undo commands.
     *
     * @param selectedItemIndex number of commands to undo
     */
    public void undoPerformed(int selectedItemIndex) {
        for (int i = 0; i <= selectedItemIndex; i++) {
            try {
                getActiveDocument().undo();
            } catch(CommandException e) {
                e.printStackTrace(); // TODO
            }
        }
    }
    
    /**
     * Redo commands.
     *
     * @param selectedItemIndex number of commands to redo
     */
    public void redoPerformed(int selectedItemIndex) {
        for (int i = 0; i <= selectedItemIndex; i++) {
            try {
                getActiveDocument().redo();
            } catch(CommandException e) {
                e.printStackTrace(); // TODO
            }
        }
    }
    
    /**
     * Notify about changes in observed object.
     * Method from interface Observer.
     *
     * @param eventCode type of CommandStack event
     */
    public void notifyFromObserved(int eventCode) {
        switch (eventCode) {
            case CommandStack.UNDO: // overflow
            case CommandStack.REDO:
            case CommandStack.EXECUTE:
                this.setUndoCommandList(this.activeCommandStack.getAvailForUndo());
                this.setRedoCommandList(this.activeCommandStack.getAvailForRedo());
                this.redoButton.setEnabled(this.activeCommandStack.redoPossible());
                this.dropRedoButton.setEnabled(this.activeCommandStack.redoPossible());
                this.undoButton.setEnabled(this.activeCommandStack.undoPossible());
                this.dropUndoButton.setEnabled(this.activeCommandStack.undoPossible());
                break;
            case Simulation.CLEAR_TRANSITIONS:
                this.firedTransitionsList.setText("");
                this.allFired.clear();
                break;
            case Simulation.TRANSITION_ADDED:
                Transition transition = getActiveDocument().getSimulation().getLastFiredTransition();
                this.allFired.add(transition);
                this.firedTransitionsList.setText(this.firedTransitionsList.getText() + "\n" + transition);
                break;
            case Simulation.TRANSITION_DELETED:
                this.allFired.remove(this.allFired.size()-1);
                this.firedTransitionsList.setText("");
                for (int i = 0; i < this.allFired.size(); i++)
                    this.firedTransitionsList.append(this.allFired.get(i) + "\n");
                break;
            case Simulation.TRANSITION_REFRESH:
                this.allFired = getActiveDocument().getSimulation().getAllFiredTransitions();
                this.firedTransitionsList.setText("");
                for (int i = 0; i < this.allFired.size(); i++)
                    this.firedTransitionsList.append(this.allFired.get(i) + "\n");
                break;
            case Simulation.SIMULATION_ERROR:
                JOptionPane.showMessageDialog(this, this.getActiveDocument().getSimulation().getErrorMessage(),
                        ResourceBundle.getBundle("edu/uj/petri/messages").getString("Error"), JOptionPane.ERROR_MESSAGE);
                break;
            default:
                System.err.printf("MainWindow: received unknown signal from observed: %d\n", eventCode);
        }
    }
    
    /**
     * Compare two MainWindows.
     * Method from interface Comparable.
     *
     * @return 0 if MainWindows' references are equal, otherwise 1
     */
    public int compareTo(Object o) {
        if (this == o)
            return 0;
        else /* no matter which reference is bigger than the second one; return 1 means 'they are different */
            return 1;
    }
    
}
